﻿namespace MicroCloud.Utils
{
    /// <summary>
    /// 密码数据类型
    /// </summary>
    [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)]
    public class PasswordAttribute : DataTypeAttribute
    {
        //字段
        private string _value;

        /// <summary>
        /// 以最小长度为6、需要数字、不允许纯数字、需要小写字母、不需要大写字母 
        /// 初始化 密码数据类型 <see cref="PasswordAttribute"/> 的新实例
        /// </summary>
        public PasswordAttribute()
            : base(DataType.Password)
        {
            RequiredLength = 6;
            RequiredDigit = true;
            CanOnlyDigit = false;
            RequiredLowercase = true;
            RequiredUppercase = false;
        }

        #region 属性
        /// <summary>
        /// 获取或设置 密码最小长度
        /// </summary>
        public int RequiredLength { get; set; }

        /// <summary>
        /// 获取或设置 需要数字
        /// </summary>
        public bool RequiredDigit { get; set; }

        /// <summary>
        /// 获取或设置 是否允许纯数字
        /// </summary>
        public bool CanOnlyDigit { get; set; }

        /// <summary>
        /// 获取或设置 需要小写字母
        /// </summary>
        public bool RequiredLowercase { get; set; }

        /// <summary>
        /// 获取或设置 需要大写字母
        /// </summary>
        public bool RequiredUppercase { get; set; }

        #endregion

        #region 方法 - Overrides of DataTypeAttribute
        /// <summary>
        /// 检查数据字段的值是否有效
        /// </summary>
        /// <param name="value">要验证的数据字段值</param>
        /// <returns>如果指定的值有效或 null，则为 true；否则，为 false</returns>
        public override bool IsValid(object value)
        {
            if (value == null)
            {
                return true;
            }
            if (value is not string input)
            {
                return false;
            }
            _value = input;
            if (input.Length < RequiredLength)
            {
                return false;
            }
            if (RequiredDigit && !input.IsMatch(@"[0-9]"))
            {
                return false;
            }
            if (!CanOnlyDigit && input.IsMatch(@"^[0-9]+$"))
            {
                return false;
            }
            if (RequiredLowercase && !input.IsMatch(@"[a-z]"))
            {
                return false;
            }
            return !RequiredUppercase || input.IsMatch(@"[A-Z]");
        }
        
        /// <summary>
        /// 基于发生错误的数据字段对错误消息应用格式设置
        /// </summary>
        /// <param name="name">要包括在带有格式的消息中的名称</param>
        /// <returns>带有格式的错误消息的实例</returns>
        public override string FormatErrorMessage(string name)
        {
            name.CheckNotNullOrEmpty(nameof(name));
            if (_value.Length < RequiredLength)
            {
                return I18N.T("{0} 长度必须大于 {1}", name, RequiredLength);
            }
            if (RequiredDigit && !_value.IsMatch(@"[0-9]"))
            {
                return I18N.T("{0} 必须包含数字", name);
            }
            if (!CanOnlyDigit && _value.IsMatch(@"^[0-9]+$"))
            {
                return I18N.T("{0} 不允许是全是数字", name);
            }
            if (RequiredLowercase && !_value.IsMatch(@"[a-z]"))
            {
                return I18N.T("{0} 必须包含小写字母", name);
            }
            if (RequiredUppercase && !_value.IsMatch(@"[A-Z]"))
            {
                return I18N.T("{0} 必须包含大写字母", name);
            }
            return base.FormatErrorMessage(name);
        }

        #endregion

    }
}